using Cyys.Map;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;


public class CameraManager : MonoBehaviour
{
    [Header("Input System")]
    public Gameplay_SO gameplayInput;

    [Header("Camera Settings")]
    public Camera mapCamera;
    public float dragSpeed = 5f;
    public float[] zoomLevels = { 1f, 2f, 3f, 4f, 5f, 6f, 7f, 9f, 10f };
    public int defaultZoomLevel = 10;

    [Header("Map Boundaries")]
    public Rect mapBounds;// x=-18, y=-10, width=36, height=20

    private int currentZoomLevel;

    private void Awake()
    {
        if (mapCamera == null)
            mapCamera = Camera.main;
    }

    private void OnEnable()
    {
        EventHandler.CameraDragEvent += OnCameraDragEvent;
        EventHandler.CameraZoomEvent += OnCameraZoomEvent;
        EventHandler.AfterSceneLoadEvent += OnAfterSceneLoadEvent;
    }

    private void OnDisable()
    {
        EventHandler.CameraDragEvent -= OnCameraDragEvent;
        EventHandler.CameraZoomEvent -= OnCameraZoomEvent;
        EventHandler.AfterSceneLoadEvent -= OnAfterSceneLoadEvent;
    }

    private void OnAfterSceneLoadEvent()
    {
        gameplayInput.EnableGameplay();

        MapData_SO currentMapData = GridMapManager.Instance.GetCurrentMapData(SceneManager.GetActiveScene().name);
        mapBounds = new Rect(currentMapData.originX, currentMapData.originY, currentMapData.gridWidth, currentMapData.gridHeight); 
        

        currentZoomLevel = Mathf.Clamp(defaultZoomLevel, 0, zoomLevels.Length - 1);
        ApplyZoomInstant();
    }

    public void SetMapBounds(Rect bounds)
    {
        mapBounds = bounds;
        ClampCameraPosition();
    }

    private void OnCameraDragEvent(Vector2 delta)
    {
        Vector3 translation = new Vector3(-delta.x, -delta.y, 0) *
                              dragSpeed *
                              mapCamera.orthographicSize *
                              0.001f;
        mapCamera.transform.Translate(translation, Space.World);
        ClampCameraPosition();
    }

    private void OnCameraZoomEvent(float scroll)
    {
        if (scroll > 0) ZoomIn();
        else if (scroll < 0) ZoomOut();
    }

    private void ZoomIn()
    {
        if (currentZoomLevel > 0)
        {
            currentZoomLevel--;
            ApplyZoomInstant();
        }
    }

    private void ZoomOut()
    {
        if (currentZoomLevel < zoomLevels.Length - 1)
        {
            currentZoomLevel++;
            ApplyZoomInstant();
        }
    }

    private void ApplyZoomInstant()
    {
        if (zoomLevels.Length == 0) return;

        Vector3 viewCenterWorldPos = mapCamera.ScreenToWorldPoint(
            new Vector3(Screen.width / 2f, Screen.height / 2f, mapCamera.nearClipPlane));

        mapCamera.orthographicSize = zoomLevels[currentZoomLevel];

        Vector3 newViewCenterWorldPos = mapCamera.ScreenToWorldPoint(
            new Vector3(Screen.width / 2f, Screen.height / 2f, mapCamera.nearClipPlane));

        mapCamera.transform.position += viewCenterWorldPos - newViewCenterWorldPos;
        ClampCameraPosition();
    }

    private void ClampCameraPosition()
    {
        if (mapCamera == null) return;

        float cameraHeight = mapCamera.orthographicSize * 2;
        float cameraWidth = cameraHeight * mapCamera.aspect;

        // 计算地图实际边界
        float mapMinX = mapBounds.x;
        float mapMaxX = mapBounds.x + mapBounds.width;
        float mapMinY = mapBounds.y;
        float mapMaxY = mapBounds.y + mapBounds.height;

        // 计算相机约束范围
        float minX = mapMinX + cameraWidth / 2;
        float maxX = mapMaxX - cameraWidth / 2;
        float minY = mapMinY + cameraHeight / 2;
        float maxY = mapMaxY - cameraHeight / 2;

        // 处理视图大于地图的情况
        if (cameraWidth > mapBounds.width)
        {
            minX = (mapMinX + mapMaxX) / 2;
            maxX = minX;
        }

        if (cameraHeight > mapBounds.height)
        {
            minY = (mapMinY + mapMaxY) / 2;
            maxY = minY;
        }

        Vector3 pos = mapCamera.transform.position;
        pos.x = Mathf.Clamp(pos.x, minX, maxX);
        pos.y = Mathf.Clamp(pos.y, minY, maxY);

        mapCamera.transform.position = pos;
    }
}